/*
 * Author: nicolas.bredeche(@)lri.fr
 * Created on 14 janv. 2006
 * 
 */

package picoevo.ext.evolution;

import picoevo.core.evolution.SelectionOperator;
import picoevo.core.representation.Population;
import picoevo.core.representation.PopulationContainer;
import picoevo.core.representation.PopulationObject;
import picoevo.core.representation.PopulationView;

/**
 * as described in Koza (1992) "A hierarchical approach to learning the boolean
 * multiplexer function".
 * 
 */
public class SelectionOperator_Koza92multiplexer extends SelectionOperator {

	public SelectionOperator_Koza92multiplexer() {
		super("GP selection operator for multiplexer [Koza92]");
	}

	public SelectionOperator_Koza92multiplexer(String __name) {
		super(__name);
	}

	@Override
	public void performSelection(PopulationObject __population) {
		PopulationContainer newpop = new PopulationContainer(); // newpop va
		// contenir ma
		// liste
		// d'individus
		// pour la
		// prochaine
		// generation
		PopulationContainer newpopbuffer; // newpopbuffer va contenir des
		// bouts de la pop finale

		// System.out.println("passed.");System.exit(-4);

		int popsize = __population.getPopulationSize();

		double segments = 10;
		double copySegments = 1;

		// step 1: fitness proportionate selection and copy of the best 10%
		if (copySegments != 0) {
			PopulationView populationView = SelectionOperator_FitnessValueProportionateReproduction.performSelectionView(__population, (int) ((popsize) * copySegments / segments));
			// PopulationView populationView =
			// SelectionOperator_FitnessRankProportionateReproduction.performSelectionView(__population,(int)(((double)popsize)*copySegments/segments));
			// PopulationView populationView =
			// SelectionOperator_SimpleRank.performSelectionView(__population,(int)(((double)popsize)*copySegments/segments));
			newpopbuffer = new PopulationContainer(populationView);
			newpop.mergeWithContainer(newpopbuffer); // newpopbuffer is
			// automaticaly emptied
			/**/
		}

		for (int i = 0; i != (int) ((popsize) * ((segments - copySegments) / segments) / 2.0); i++) {
			newpopbuffer = new PopulationContainer();
			// Individual ind =
			// (SelectionOperator_FitnessProportionateReproduction.performSelectionView(__population,1)).getIndividual(0);
			newpopbuffer.cloneAndRegisterIndividual((SelectionOperator_FitnessValueProportionateReproduction.performSelectionView(__population, 1)).getIndividual(0)); // ind.
			// 1
			// (proportionate
			// selection)
			// newpopbuffer.cloneAndRegisterIndividual((SelectionOperator_FitnessRankProportionateReproduction.performSelectionView(__population,1)).getIndividual(0));
			// // ind. 1 (proportionate selection)
			newpopbuffer.cloneAndRegisterIndividual(__population.getIndividual((int) (Math.random() * popsize))); // ind.
			// 2
			// (random
			// selection)

			newpopbuffer.addOperatorList(__population.getVariationOperatorList());

			newpopbuffer.performVariations(); // an individual may be subject
			// to more than one variation...
			// ERROR?

			newpop.mergeWithContainer(newpopbuffer); // newpopbuffer is
			// automaticaly emptied
		}

		((Population) __population).renewPopulation(newpop); // newpop is
		// emptied
	}
}
